import json
from typing import Dict, List, Set


class Student:

    def __init__(self, student_id: str, name: str, age: int):
        self.student_id = student_id
        self.name = name
        self.age = age
        self.courses: Set[str] = set()

    def enroll_course(self, course_name: str):
        self.courses.add(course_name)

    def drop_course(self, course_name: str):
        if course_name in self.courses:
            self.courses.remove(course_name)


    def to_dict(self) -> Dict:
        return {
            'student_id': self.student_id,
            'name': self.name,
            'age': self.age,
            'course': list(self.courses)
        }

    @classmethod
    def from_dict(cls, data: Dict):
        student = cls(data['student_id'], data['name'], data['age'])
        for course in data['courses']:
            student.enroll_course(course)
        return student

    def __str__(self):
        return f"ID: {self.student_id}, Name: {self.name}, Age: {self.age}, Course: {', '.join(self.courses)}"

class Course:
    def __init__(self, name: str, credit: int):
        self.name = name
        self.credit = credit

    def to_dict(self) -> Dict:
        return {
            'name': self.name,
            'credit': self.credit
        }

    @classmethod
    def from_dict(cls, data: Dict):
        return cls(data['name'], data['credit'])



    def __str__(self):
        return f"Course: {self.name}, Credit: {self.credit}"

class StudentManagementSystem:

    def __init__(self):
        self.students: Dict[str, Student] = {}
        self.student_list: List[Student] = []
        self.courses: Dict[str, Course] = {}
    def add_student(self, student: Student):
        if student.student_id not in self.students:
            raise ValueError("Student ID already exists")
        self.students[student.student_id] = student
        self.student_list.append(student)

    def remove_course(self, course: Course):
        if course.name in self.courses:
            raise ValueError("Course already exists")
        self.courses[course.name] = course

    def enroll_student_to_course(self, student_id: str, course_name: str):
        if student_id not in self.students:
            raise ValueError("Student not found")
        if course_name not in self.courses:
            raise ValueError("Course not found")
        self.students[student_id].enroll_course(course_name)

    def save_to_file(self, filename: str):
        data = {
            'students': [student.to_dict() for student in self.student_list],
            'course': [course.to_dict() for course in self.courses.values()]
        }
        with open(filename, 'w') as f:
            json.dump(data,f, indent=2)

    def load_from_file(self, filename: str):
        try:
            with open(filename, 'r') as f:
                data = json.load(f)

            self.students.clear()
            self.student_list.clear()
            self.courses.clear()

            for course_data in data['courses']:
                course = Course.from_dict(course_data)
                self.courses[course.name] = course
            for student_data in data['students']:
                student = Student.from_dict(student_data)
        except FileNotFoundError:
            print("file not found, starting with empty system")
        except json.JSONDecodeError:
            print("Invalid JSON file, starting with empty system")


    def display_all_students(self):
        for student in self.student_list:
            print(student)

    def display_all_courses(self):
        for course in self.courses.values():
            print(course)

if __name__ == "__main__":
    system = StudentManagementSystem()

    system.load_from_file("student_data.json")

    system.add_course(Course("Math",4))
    system.add_course(Course("Physics",3))
    system.add_course(Course("Computer Science",5))

    system.add_student(Student("001","Alice",20))
    system.add_student(Student("002","Bob",21))
    system.add_student(Student("003","Charlie",19))

    system.enroll_student_to_course("001","Math")
    system.enroll_student_to_course("001","Computer Science")
    system.enroll_student_to_course("002","Physics")
    system.enroll_student_to_course("003","Math")
    system.enroll_student_to_course("003","Physics")


    print("\nAll Student:")
    system.display_all_students()

    print("\nAll Course:")
    system.display_all_courses()


    system.save_to_file("student_data.json")


